package yang_exp.concurrent;
import java.util.*;
import java.util.concurrent.TimeUnit;
/* 
    生产者消费者模式1：利用sync实现
    线程操作资源类
*/
public class ConsumnerAndProductor1 {
   
    static class MyResource {
        private int count = 0;
        /* 
            不安全的方式，使用Integer
        */
        Queue<Integer> production;
        int capacity;
        /* 
            在构造方法中传递共享资源
        */
        public MyResource(int capacity, Queue<Integer> production) {
            this.production = production;
            this.capacity = capacity;
        }

        public void product() {
            synchronized (production) {
                /* 
                    使用while, 防止虚假唤醒
                */
                while (this.production.size() == capacity) {
                    //达到最大容量，不能生产，沉睡等待
                    try {
                        production.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                System.out.println("生产者" + Thread.currentThread().getName() + "生产了" + count);
                production.add(count++);
                try {
                    TimeUnit.SECONDS.sleep(2);
   
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }   
                production.notifyAll();   
            }
        }

        public void consume() {
            synchronized (production) {
                while (production.size() == 0) {
                    try {
                        production.wait();
                    } catch (InterruptedException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                }
                System.out.println("消费者" + Thread.currentThread().getName() + "消费了资源" + production.poll());
                try {
                    TimeUnit.SECONDS.sleep(2);
   
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }            production.notifyAll();
            }
        } 
    }

    public static void main(String[] args) {
         MyResource mr = new MyResource(5, new LinkedList<>());

         for (int i = 0; i < 100; i++) {
             new Thread(() -> {
                mr.product();
             }, "productor" + i).start();

             new Thread(() -> {
                mr.consume();
             }, "consumer" + i).start();
         }
    }

}
